// Code markups
// IEFIX: Code adapted to IE bugfix
// FFFIX: Code adapted to Firefox bugfix

/**
 * The main syslib class
 * @namespace syslib
 * @version 0.5.5
 * @author Gabriel Ricci - gabrielricci@gmail.com
 * @static
 */
var syslib = {
	version: "0.5.5",
	
	path: "",
	lookAndFeel: "default/",
	componentsPath: this.path + "themes/",
	srcPath: this.path + "src",
	debug: false,
	
	options: {
		path: "",
		lookAndFeel: "",
		debug: false,
		enableUI: false,
		enableFX: false,
		effects: []
	},
	
	init: function(options){
		if (options.constructor == Object) {
			// extend the options
			this.options = __extend(this.options, options);
			
			// path
			if (__valid(this.options.path)) {
				if (this.options.path.charAt(options.path.length + 1) != "/") {
					this.path = this.options.path + "/";
				} else {
					this.path = this.options.path;
				}
				this.srcPath = this.path + "src/";
				this.componentsPath = this.path + "components/";
			}
			var path = this.path;
			
			// look and feel
			if (__valid(options.lookAndFeel)) {
				// create the theme path
				if (options.lookAndFeel.charAt(options.lookAndFeel.length) != "/") {
					this.lookAndFeel = options.lookAndFeel + "/";
				} else {
					this.lookAndFeel = options.lookAndFeel;
				}
				
				// load the theme main css file
				syslib.io.importStyle(syslib.path + "themes/" + syslib.lookAndFeel + "style.css");
			}
			
			// debug
			if (this.options.debug) {
				// set the debug flag 
				syslib.debug = true;
				
				syslib.event.listen("load", window, function(){
					// create the console
					syslib.console.createConsole();
				});
				
				// events
				window.onerror = function(err, url, line){
					syslib.messages.error("Javascript error(" + (url) + ") on line " + line + ", see: " + err);
				};
			}
			
			// user interface
			if (__valid(this.options.enableUI) && this.options.enableUI === true) {
				// schedule the loader
				syslib.event.listen("load", window, function(){
					// import the user interface component
					syslib.io.importScript(path + "syslib.ui.js", {
						onComplete: function(){
							// verbose
							syslib.messages.info("syslib.init(): User interface components loaded");
							
							// try to start the ui system
							var attempts = 1;
							var started = false;
							while (!started && attempts <= 200) {
								try {
									// start the ui
									syslib.ui.init();
									
									// set as started and cancel the loop
									started = true;
								} catch (e) {
									// increase the number of attempts
									attempts++;
									
									// set as not started and go to the next loop
									started = false;
									continue;
								}
							}
						}
					});
				});
			}
			
			// history
			if (!__valid(options.history || options.history === true)) {
				setTimeout(function(){
					// load te history engine
					syslib.history.init();
				}, 2000);
			}
		}
	},
	
	/**
	 * Load the stylesheet for the component
	 * @param {Object} component The specified component
	 */
	loadStyleForComponent: function(component){
		syslib.io.importStyle(syslib.path + "themes/" + syslib.lookAndFeel + component + "/style.css");
	},
	
	loadStyle: this.loadStyleForComponent,
	
	/**
	 * Get the path of the component
	 * @return The path of the component specified (String)
	 * @param component (String)
	 */
	getComponentPath: function(component){
		var path = syslib.path + "components/" + syslib.lookAndFeel + component + "/";
		return path;
	},
	
	namespace: function(namespace){
		// split the namespace name
		var parts = namespace.split(".");
		
		// set the root
		var root = syslib;
		
		// search the parts
		for (var i in parts) {
			// check if the part is valid and the part exist
			if (parts[i] != "syslib") {
				// get the part
				var part = parts[i];
				
				if (!__valid(root[part]) || typeof root[part] != "object") {
					root[part] = {};
				}
				
				// set the new root
				root = root[part];
			}
		}
	}
};

// aliases for the syslib namespace
var __debug = syslib.debug;
var __options = syslib.options;


/**
 * Syslib utilities class
 * @namespace syslib.util
 * @author Gabriel Ricci
 * @static
 */
syslib.util = {
	isIE: function(){
		return (navigator.appName.indexOf('Internet Explorer') > -1) ? true : false;
	},
	
	isGecko: function(){
		return (navigator.userAgent.indexOf('Gecko') > -1) ? true : false;
	},
	
	isOpera: function(){
		return (navigator.userAgent.indexOf('Opera') > -1) ? true : false;
	},
	
	isChrome: function(){
		return (navigator.userAgent.indexOf('Chrome') > -1) ? true : false;
	},
	
	isFirefox: function(){
		return (navigator.userAgent.indexOf('Firefox') > -1) ? true : false;
	},
	
	isNetscapeCompatible: function(){
		return (navigator.appName.indexOf('Netscape') > -1) ? true : false;
	},
	
	fromKeyCode: function(code){
		if (this.isIE()) {
			switch (code) {
				case 96:
					return 0;
				case 97:
					return 1;
				case 98:
					return 2;
				case 99:
					return 3;
				case 100:
					return 4;
				case 101:
					return 5;
				case 102:
					return 6;
				case 103:
					return 7;
				case 104:
					return 8;
				case 105:
					return 9;
				default:
					return String.fromCharCode(code);
			}
		} else {
			return String.fromCharCode(code);
		}
	},
	
	valid: function(elem){
		return (elem === undefined || elem === null || elem === false || elem === "") ? false : true;
	},
	
	emptyFunction: function(){
	}
};

// aliases for the syslib.util namespace
var __valid = syslib.util.valid;
var __emptyFunc = syslib.util.emptyFunction;


/**
 * The object class
 * @namespace syslib.object
 * @author Gabriel Ricci
 * @static
 */
syslib.object = {
	createClass: function(base, data){
		// create the class
		function newClass(){
			if (typeof this.__construct === 'function') {
				this.__construct.apply(this, arguments);
			}
		}
		
		// get the prototype
		var prototype = newClass.prototype;
		
		// extend
		if (__valid(base)) {
			prototype = __extend(prototype, base);
		}
		if (__valid(data)) {
			prototype = __extend(prototype, data);
		}
		
		// set the prototype
		newClass.prototype = prototype;
		
		// return
		return newClass;
	},
	
	extend: function(source, data){
		// check the integrity of the objects
		if (!syslib.util.valid(source)) {
			if (__valid(data)) {
				return data;
			} else {
				return false;
			}
		}
		if (!syslib.util.valid(data)) {
			return __clone(source);
		}
		
		// clone the source
		var object = __clone(source);
		
		// set the superclass
		if (__valid(object.prototype)) {
			object.prototype.__super = source.prototype;
		} else {
			object.__super = source;
		}
		
		// copy the properties
		for (var item in data) {
			if (__valid(object.prototype)) {
				object.prototype[item] = data[item];
			} else {
				object[item] = data[item];
			}
		}
		
		// return
		return object;
	},
	
	addMethods: function(sourceObject, methods){
		// add the methods
		for (var method in methods) {
			sourceObject[method] = methods[method];
		}
	},
	
	clone: function(src){
		// if the source isn't an object, just return it as it is
		if ((typeof src != "object" && typeof src != "function") || !__valid(src)) {
			alert("returning");
			return src;
		}
		
		// clone the constructor
		var cloned = (__valid(src.prototype)) ? function(){
		}
 : {};
		var source = (__valid(src.prototype)) ? src.prototype : src;
		var target = (__valid(src.prototype)) ? cloned.prototype : cloned;
		
		// set the values
		for (var item in source) {
			target[item] = source[item];
		}
		
		// return
		return cloned;
	},
	
	serialize: function(object){
		var serialized = "";
		for (var i in object) {
			serialized += "&" + i + "=" + object[i];
		}
		
		return serialized;
	},
	
	findFromName: function(objectName){
		// split the object parts and get the parts length
		var parts = objectName.split(".");
		var length = parts.length;
		
		// create the actual object
		var createdObject = window;
		
		// search the parts
		for (var i = 0; i < length; i++) {
			// update the actual object
			createdObject = createdObject[parts[i]];
			
			// check the integrity
			if (!__valid(createdObject)) {
				return;
			}
		}
		
		// return the found object
		return createdObject;
	}
};

// aliases for the syslib.object namespace
var __class = syslib.object.createClass;
var __clone = syslib.object.clone;
var __extend = syslib.object.extend;
var __addMethods = syslib.object.addMethods;


/**
 * Element namespace
 * @namespace syslib.element
 * @static
 */
syslib.element = {
	innerAttributes: null,
	
	getById: function(elmt){
		// get the element
		if (typeof elmt != "object") {
			elmt = document.getElementById(elmt);
		}
		
		// check the element integrity
		if (!__valid(elmt)) {
			return false;
		}
		
		// check the element extensions
		if (!__valid(elmt.getCSSProperty)) {
			syslib.element.addCustomMethods(elmt);
		}
		
		// return
		return elmt;
	},
	
	addCustomMethods: function(elmt){
		// add the syslib.css methods
		__addMethods(elmt, syslib.css.__prototype);
		
		// add the syslib.element methods
		__addMethods(elmt, syslib.element.__prototype);
	},
	
	setAttribute: function(element, attribute, value){
		// set the attribute using the w3c method
		element.setAttribute(attribute, value);
		
		// IEFIX: The setAttribute method doesn't work on IE, so we give it special treatment
		if (attribute == "class") {
			element.className = value;
		} else if (attribute == "name") {
			element.name = value;
		} else if (attribute == "enctype") {
			element.encoding = value;
			element.encType = value;
		} else if (attribute == "checked") {
			element.checked = true;
		} else if (attribute == "style") {
			element.style.cssText = value;
		} else if (attribute == "cellpadding") {
			element.cellPadding = value;
		} else if (attribute == "cellspacing") {
			element.cellSpacing = value;
		} else if (attribute == "colspan") {
			element.colSpan = value;
		} else if (attribute == "rowspan") {
			element.rowSpan = value;
		} else if (attribute.substr(0, 2) == "on") { // for all events
			element[attribute] = new Function(value);
		}
	},
	
	generateID: function(){
		return "syslib_generated_id-" + (Math.random() * 100);
	},
	
	createFromJSON: function(parent, nodeContent){
		// create the node
		var node;
		
		// search the node content
		for (var i = 0; i < nodeContent.length; i++) {
			if (nodeContent[i] === undefined || nodeContent[i] === null) {
				// undefined element, show the error
				syslib.messages.warning("syslib.element.createFromJSON(): Impossible to draw an undefined element!");
			} else if (__valid(nodeContent[i].tagName)) {
				// dom node, set as the element itself
				node = nodeContent[i];
			} else if (i === 0 && nodeContent[i].constructor == String) {
				// root node, create the element
				node = document.createElement(nodeContent[i]);
				
				// check if the parent is setted
				if (!syslib.util.valid(parent)) {
					this.innerAttributes = {};
				}
			} else if (nodeContent[i].constructor == Object) {
				// attributes, search all the attributes
				for (attr in nodeContent[i]) {
					// check if the attribute value if valid
					if (!__valid(nodeContent[i][attr])) {
						continue;
					}
					
					// check if the attribute is the innerName
					if (attr.toLowerCase() == "innername") {
						this.innerAttributes[nodeContent[i][attr]] = node;
					} else {
						// normal attribute, set the value
						syslib.element.setAttribute(node, attr, nodeContent[i][attr]);
					}
				}
			} else if (nodeContent[i].constructor == Array) {
				// child nodes, call the recursion
				syslib.element.createFromJSON(node, nodeContent[i]);
			} else if (i !== 0 && nodeContent[i].constructor == String) {
				// string content, append to innerHTML
				node.innerHTML += nodeContent[i];
			}
		}
		
		// append to the parent, is the parent is setted
		if (__valid(parent)) {
			parent.appendChild(node);
		}
		
		// return
		return {
			element: node,
			references: this.innerAttributes
		};
	},
	
	hide: function(elmt){
		// get the elememt
		elmt = __id(elmt);
		
		// check the element integrity
		if (!__valid(elmt)) {
			syslib.messages.warning("syslib.element.hide(): Invalid element!");
			return false;
		}
		
		// check if the actual display mode must be stored
		if (typeof elmt._originalDisplayMode == "undefined") {
			// get the actual display mode
			var display = elmt.getCSSProperty("display");
			
			// store, if needed
			if (display !== false && display != "none") {
				elmt._originalDisplayMode = display;
			}
		}
		
		// hide
		elmt.setCSSProperty("display", "none");
		elmt.setCSSProperty("visibility", "hidden");
		
		// return
		return elmt;
	},
	
	show: function(elmt){
		// get the elememt
		elmt = __id(elmt);
		
		// check the element integrity
		if (!__valid(elmt)) {
			syslib.messages.warning("syslib.element.show(): Invalid element!");
			return false;
		}
		
		// check if the element have the original display mode stored
		if (__valid(elmt._originalDisplayMode)) {
			// get the original display mode
			var display = elmt._originalDisplayMode;
			
			// show the element
			elmt.setCSSProperty("display", display);
		} else {
			// check the element display mode
			if (elmt.tagName.toLowerCase() == "span" || elmt.tagName.toLowerCase() == "a") {
				elmt.setCSSProperty("display", "inline");
			} else if (elmt.tagName.toLowerCase() == "td") {
				elmt.setCSSProperty("display", "");
			} else {
				elmt.setCSSProperty("display", "block");
			}
		}
		
		// set the visibility style
		elmt.setCSSProperty("visibility", "visible");
		
		// return
		return elmt;
	},
	
	
	isVisible: function(element){
		element = __id(element);
		style = element.style;
		
		if (!__valid(element)) {
			return false;
		}
		if (!__valid(style)) {
			return true;
		}
		
		if (style.display != "none" && style.visibility != "hidden") {
			if (element.parentNode) {
				return this.isVisible(element.parentNode);
			} else {
				return true;
			}
		} else {
			return false;
		}
	},
	
	getDimensions: function(element){
		element = __id(element);
		return {
			width: element.offsetWidth,
			height: element.offsetHeight
		};
	},
	
	toggleVisibility: function(element){
		if (this.isVisible(element)) {
			this.hide(element);
		} else {
			this.show(element);
		}
	},
	
	update: function(element, value){
		value = (!syslib.util.valid(value)) ? '' : value;
		element = __id(element);
		
		element.innerHTML = value;
	},
	
	updateStyle: function(element, style){
		syslib.css.updateStyle(element, style);
	},
	
	/**
	 * @private
	 */
	__prototype: {
		show: function(){
			return syslib.element.show(this);
		},
		hide: function(){
			return syslib.element.hide(this);
		},
		isVisible: function(){
			return syslib.element.isVisible(this);
		},
		toggleVisibility: function(){
			return syslib.element.toggleVisibility(this);
		},
		getDimensions: function(){
			return syslib.element.getDimensions(this);
		}
	}
};

// aliases for the syslib.element namespace
var __id = syslib.element.getById;
var __createFromJSON = syslib.element.createFromJSON;
var __hide = syslib.element.hide;
var __show = syslib.element.show;


/**
 * Syslib CSS namespace
 * @namespace syslib.util
 * @author Gabriel Ricci
 * @static
 */
syslib.css = {
	getProperty: function(element, property){
		// get the element
		element = __id(element);
		
		// check the integrity
		if (!__valid(element)) {
			return false;
		}
		
		// return 
		return element.style[property];
	},
	
	setProperty: function(element, property, value){
		// create the new style object
		var style = {};
		
		// set the new style property
		style[property] = value;
		
		// update the style
		this.updateStyle(element, style);
	},
	
	updateStyle: function(element, style){
		// get the element
		element = __id(element);
		
		// check if the element and the style are valid
		if (__valid(element) && __valid(style)) {
			for (var name in style) {
				// set the style
				var value = style[name];
				element.style[name] = value;
			}
		}
	},
	
	addClass: function(element, className){
		// get the element
		element = __id(element);
		
		// add the class
		element.className = element.className + " " + className;
	},
	
	removeClass: function(element, className){
		// get the element
		element = __id(element);
		
		// get the elements classes
		var classes = element.className;
		
		// format the classes
		classes = syslib.string.replace(className, "", classes);
		
		// set the classes
		element.className = classes;
	},
	
	/**
	 * @private
	 */
	__prototype: {
		getCSSProperty: function(property){
			return syslib.css.getProperty(this, property);
		},
		setCSSProperty: function(property, value){
			return syslib.css.setProperty(this, property, value);
		},
		updateStyle: function(style){
			return syslib.css.updateStyle(this, style);
		},
		addClass: function(className){
			return syslib.css.updateStyle(this, className);
		},
		removeClass: function(className){
			return syslib.css.updateStyle(this, className);
		}
	}
};

/**
 * DOM namespace
 * @namespace syslib.dom
 * @author Gabriel Ricci
 * @static
 */
syslib.dom = {
	/**
	 * @private
	 */
	__navigator: function(element, search){
		element = __id(element);
		var parent = element.parentNode;
		var childs = [];
		
		if (!__valid(parent)) {
			childs = [];
		} else {
			childs = parent.childNodes;
		}
		
		for (var i = 0; i < childs.length; i++) {
			var child = childs[i];
			if (child === element) {
				var index = i;
				var returnChild = null;
				switch (search) {
					case "next":
						index++;
						returnChild = childs[index];
						return (syslib.util.valid(returnChild)) ? returnChild : false;
						
					case "previous":
						index--;
						returnChild = childs[index];
						return (syslib.util.valid(returnChild)) ? returnChild : false;
						
				}
			}
		}
	},
	
	next: function(element){
		return this.__navigator(element, 'next');
	},
	
	previous: function(element){
		return this.__navigator(element, 'previous');
	}
};

/**
 * The functions class
 * @namespace syslib.functions
 * @author Gabriel Ricci
 * @static
 */
syslib.functions = {
	applyTo: function(method, object){
		return function(){
			return method.apply(object, arguments);
		};
	},
	
	/**
	 * @private
	 */
	__prototype: {
		applyTo: function(object){
			if (!__valid(object.isApplyTo)) {
				return syslib.functions.applyTo(this, object);
			}
		}
	}
};

// extensions for the functios object
__addMethods(Function.prototype, syslib.functions.__prototype);


/**
 * Event namespace
 * @namespace syslib.event
 * @author Gabriel Ricci
 * @static
 */
syslib.event = {
	getElement: function(evt){
		if (syslib.util.isIE()) {
			return window.event.srcElement;
		} else {
			return evt.target;
		}
	},
	
	getKeyCode: function(evt){
		return window.event ? window.event.keyCode : evt.which;
	},
	
	isSpecialCode: function(evt){
		var code = this.getKeyCode(evt);
		var special = false;
		var scodes = [8, 13, 36, 35, 46, 0, 45, 33, 34, 9, 16, 17, 18, 37, 38, 39, 40];
		
		for (var i in scodes) {
			var scode = scodes[i];
			if (scode == code) {
				special = true;
			}
		}
		
		return special;
	},
	
	listen: function(eventName, element, observer, useCapture){
		if (!__valid(element)) {
			syslib.messages.error("syslib.event.listen(): Element invalid for event " + eventName);
			return false;
		}
		
		useCapture = useCapture || false;
		if (element.addEventListener) {
			element.addEventListener(eventName, observer, useCapture);
		} else if (element.attachEvent) {
			element.attachEvent('on' + eventName, observer);
		}
	},
	
	stopPropagation: function(event){
		// get the event
		if(!__valid(event)){
			if(!__valid(window.event)){
				return syslib.messages.error("syslib.event.stopPropagation(): Invalid event");
			} else {
				event = window.event;
			}
		}
		
		// check the w3c methods
		if (event.preventDefault) {
      		event.preventDefault();
      		event.stopPropagation();
    	} else {
      		event.returnValue = false;
      		event.cancelBubble = true;
    	}
	},
	
	stopListening: function(){
		syslib.messages.info("syslib.event.stopListening(): This function is not implemented yet!");
	},
	
	isLeftClick: function(event){
		return (((event.which) && (event.which == 1)) ||
		((event.button) && (event.button == 1)));
	},
	
	mouseX: function(event){
		return event.pageX || (event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft));
	},
	
	mouseY: function(event){
		return event.pageY || (event.clientY + (document.documentElement.scrollTop || document.body.scrollTop));
	}
};

// aliases for the event namespace
var __evtListen = syslib.event.listen;


/**
 * String namespace
 * @namespace syslib.string
 * @author Gabriel Ricci
 * @static
 */
syslib.string = {
	REPLACE_TYPE_ONE: "REPLACE_TYPE_ONE",
	REPLACE_TYPE_ALL: "REPLACE_TYPE_ALL",
	REPLACE_DIRECTION_TOPBOTTOM: "REPLACE_DIR_TB",
	REPLACE_DIRECTION_BOTTOMTOP: "REPLACE_DIR_BT",
	
	__UNICODE_TABLE: {
		"<": "&#60;",
		">": "&#62;",
		'"': "&#38;",
		"'": "&#34;",
		" ": "&#32;",
		"&": "&#38;",
		"?": "&#63;",
		"=": "&#61;",
		":": "&#58;"
	},
	
	__HTML_TABLE: {
		"<": "&lt;",
		">": "&gt;",
		'"': "&quot;",
		"'": "&quot;",
		" ": "&nbsp;",
		"&": "&amp;"
	},
	
	encodeHTMLEntities: function(text){
		this.encode(text, this.__HTML_TABLE);
	},
	
	decodeHTMLEntities: function(text){
		this.decode(text, this.__HTML_TABLE);
	},
	
	encodeUnicodeEntities: function(text){
		this.encode(text, this.__UNICODE_TABLE);
	},
	
	decodeUnicodeEntities: function(text){
		this.decode(text, this.__UNICODE_TABLE);
	},
	
	encode: function(text, table){
		// create the encoded text
		var encoded = text;
		
		// seach the text
		for (var i in table) {
			// get the special char
			var ch = table[i];
			
			// decode
			encoded = this.replace(i, ch, encoded);
		}
		
		return encoded;
	},
	
	decode: function(text, table){
		// create the encoded text
		var decoded = text;
		
		// seach the text
		for (var i in table) {
			// get the special char
			var ch = table[i];
			
			// decode
			decoded = this.replace(ch, i, decoded);
		}
		
		return decoded;
	},
	
	pad: function(str, length, padWith){
		if (str.length >= length) {
			return str;
		}
		
		if (typeof str !== 'string') {
			str = str.toString();
			if (typeof str !== 'string') {
				return str;
			}
		}
		
		var appendString = "";
		var neededLength = length - str.length;
		
		for (var i = 1; i <= neededLength; i++) {
			appendString = padWith + appendString;
		}
		
		str = appendString + str;
		return str;
	},
	
	replace: function(needle, replaceWith, str, options){
		options = syslib.object.extend({}, options);
		type = options.type;
		direction = options.direction;
		
		var parts = str.split(needle);
		var text = parts.join(replaceWith);
		
		parts = null;
		return text;
	},
	
	reverse: function(str){
		var newStr = "";
		for (var i = str.length; i > 0; i--) {
			newStr = newStr + str.charAt((i - 1));
		}
		return newStr;
	},
	
	/** 
	 * @private
	 */
	__prototype: {
		strReplace: function(needle, replaceWith, options){
			return syslib.string.replace(needle, replaceWith, this, options);
		},
		pad: function(length, padWith){
			return syslib.string.pad(this, length, padWith);
		},
		reverse: function(){
			return syslib.string.reverse(this);
		},
		encodeHTMLEntities: function(){
			return syslib.string.encodeHTMLEntities(this);
		},
		decodeHTMLEntities: function(){
			return syslib.string.decodeHTMLEntities(this);
		}
	}
};

/**
 * Aliases and extensions for string class
 */
__addMethods(String.prototype, syslib.string.__prototype);


/**
 * Syslib math class
 * @namespace syslib.math
 * @author Gabriel Ricci
 * @static
 */
syslib.math = {
	toNegative: function(number){
		if (number < 0) {
			return number;
		} else {
			return number * -1;
		}
	}
};

/**
 * Aliases and extensions for math class
 */
__addMethods(Math, syslib.math);


/**
 * The array class
 * @namespace syslib.array
 * @author Gabriel Ricci
 * @static
 */
syslib.array = {
	clone: function(array){
		var newArray = [];
		for (var i = 0; i < array.length; i++) {
			newArray[i] = array[i];
		}
		return newArray;
	},
	
	flip: function(subject){
		// create the needed variables
		var fliped = {};
		
		// search the entries 
		for (var i in subject) {
			// set the value
			fliped[subject[i]] = i;
		}
		
		// return
		return fliped;
	}
};

/**
 * The form class
 * @namespace syslib.form
 * @author Gabriel Ricci
 * @static
 */
syslib.form = {
	validate: function(form, nrf, options){
		if (!__valid(form) || !__valid(form.elements)) {
			return true;
		}
		
		// format the options
		if (!__valid(options) || typeof options == "boolean") {
			options = {};
		}
		options = __extend({
			onlyVisible: true,
			showErrorFields: false
		}, options);
		
		// create the required variables
		var checks = [];
		var radios = [];
		var elements = [];
		var nr = (typeof nrf == 'string') ? nrf : "";
		
		// search for elements in the form
		for (var i = 0; i < form.elements.length; i++) {
			var element = form.elements[i];
			
			// verify if the element is required in the validation
			if (element.getAttribute("_required") == "false" || element.getAttribute("_required") === false) {
				continue;
			}
			
			// verify the value of the element
			if (element.value === "") {
				// verify if the element is required
				if (nr.indexOf(element.name) == -1) {
					// verify if the element is disabled or read-only
					if (element.disabled !== true && element.readOnly !== true) {
						// verify if the validation includes invisible fields
						if (__valid(options.onlyVisible) && options.onlyVisible === true) {
							if (!syslib.element.isVisible(element)) {
								continue;
							}
						}
						
						// log the error
						syslib.messages.warning("syslib.form.validate(): The field " + element.name + " is invalid for the form!");
						
						// return
						return false;
					}
				}
				// checkbox
			} else if (element.type == 'checkbox') {
				// verify if the validation includes invisible fields
				if (__valid(options.onlyVisible) && options.onlyVisible === true) {
					if (!syslib.element.isVisible(element)) {
						continue;
					}
				}
				var newName = element.name;
				if (newName.indexOf('[]') != -1) {
					newName = newName.replace("[]", "");
					if (!syslib.util.valid(checks[newName]) || checks[newName] === false) {
						checks[newName] = element.checked;
						elements[newName] = element;
					}
				}
				// radio
			} else if (element.type == "radio") {
				// verify if the validation includes invisible fields
				if (__valid(options.onlyVisible) && options.onlyVisible === true) {
					if (!syslib.element.isVisible(element)) {
						continue;
					}
				}
				var name = element.name;
				if (!syslib.util.valid(radios[name]) || radios[name] === false) {
					radios[name] = element.checked;
					elements[name] = element;
				}
			}
		}
		
		// verify the checkboxes
		for (check in checks) {
			if (checks[check] === false) {
				if (nr.indexOf(check) == -1) {
					return false;
				}
			}
		}
		
		// verify the radios
		for (radio in radios) {
			if (radios[radio] === false) {
				if (nr.indexOf(radio) == -1) {
					return false;
				}
			}
		}
		
		// return
		return true;
	},
	
	serialize: function(form){
		var elements = form.elements;
		var parts = [];
		
		for (var i = 0; i < elements.length; i++) {
			var element = form.elements[i];
			if (element.disabled) {
				continue;
			}
			var name = (syslib.util.valid(element.name)) ? encodeURIComponent(element.name) : false;
			if (!__valid(name)) {
				continue;
			}
			
			if (element.type === 'checkbox') {
				if (element.name.indexOf("[]") != -1) {
					value = (element.checked === true ? element.value : false);
				} else {
					value = (element.checked === true ? "on" : "off");
				}
				if (__valid(value)) {
					parts.push(name + '=' + value);
				}
				continue;
			}
			
			if (element.type === "radio") {
				value = (element.selected === true || element.checked === true) ? element.value : false;
				if (__valid(value)) {
					parts.push(name + '=' + value);
				}
				continue;
			}
			
			if (element.tagName.toLowerCase() === "select") {
				for (var c = 0; c < element.options.length; c++) {
					var option = element.options[c];
					if (!option.selected) {
						continue;
					}
					value = (__valid(option.value)) ? encodeURIComponent(option.value) : false;
					if (__valid(value)) {
						parts.push(name + '=' + value);
					}
				}
				continue;
			}
			
			value = (element.value !== undefined) ? encodeURIComponent(element.value) : element.name;
			if (__valid(value)) {
				parts.push(name + '=' + value);
			}
		}
		
		return parts.join("&");
	}
};

/**
 * Aliases and extensions for math class
 */
Form = syslib.form;

/**
 * XML class
 * @namespace syslib.xml
 */
syslib.xml = {
	createFromText: function(text){
		try {
			// ie
			var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
			xmlDoc.async = false;
			var loaded = xmlDoc.loadXML(text);
			
			if (!loaded) {
				alert("syslib.xml.createFromText(): Error reading the specified XML, probably the XML is not well-formed!");
				return false;
			}
			
			return xmlDoc;
		} catch (e) {
			try {
				// firefox / opera / etc
				var parser = new DOMParser();
				return parser.parseFromString(text, "application/xhtml+xml");
			} catch (ex) {
				syslib.messages.error("syslib.xml.createFromText(): You browser doesn't support dynamic XML creation!");
				return false;
			}
		}
	},
	
	convertXmlToHTML: function(xmlNode){
		// get the tagname
		var tagName = xmlNode.tagName;
		var element = null;
		
		// create the element
		// IEFIX: Internet explorer can't set the 'name' attribute, so if the element have the 'name' 
		// IEFIX: attribute setted, we create the element with the 'name' attribute setted by default
		try {
			if (syslib.util.isIE() && __valid(xmlNode.getAttribute("name")) && xmlNode.getAttribute("name") != "") {
				var name = xmlNode.getAttribute("name");
				element = document.createElement("<" + tagName + " name='" + name + "' />");
			} else {
				element = document.createElement(tagName);
			}
		} catch (e) {
			syslib.messages.error("syslib.xml.convertXmlToHTML: Error creating the element: " + e.message);
		}
		
		// get the attributes
		var attributes = this.convertAttributesToObject(xmlNode.attributes);
		
		// search the attributes
		for (var attribute in attributes) {
			// set the attribute
			syslib.element.setAttribute(element, attribute, attributes[attribute]);
		}
		
		// return
		return element;
	},
	
	convertXmlToText: function(xmlNode){
		var text = "";
		// check 
		if (xmlNode.nodeType == 1 && __valid(xmlNode.tagName)) {
			// create the tag
			text += "<" + xmlNode.tagName + " ";
			
			// get the attributes
			var attributes = xmlNode.attributes;
			
			// search the attributes
			for (var i = 0; i < attributes.length; i++) {
				// get the attribute
				attribute = attributes[i];
				
				// convert
				text += attribute.name + "=\"" + attribute.value + "\" ";
			}
			
			// close the tag
			text += ">";
			
			// search the childs
			for (var c = 0; c < xmlNode.childNodes.length; c++) {
				// convert the child
				text += this.convertXmlToText(xmlNode.childNodes[c]);
			}
			
			// close the tag
			text += "</" + xmlNode.tagName + ">";
		} else {
			// text node, just get the value
			text += xmlNode.nodeValue;
		}
		
		return text;
	},
	
	innerHTML: function(xmlNode){
		// create the variables
		var text = "";
		
		// search the child nodes
		for (var i = 0; i < xmlNode.childNodes.length; i++) {
			// get the child
			var child = xmlNode.childNodes[i];
			
			// convert
			text += this.convertXmlToText(child);
		}
		
		// return
		return text;
		
	},
	
	convertAttributesToObject: function(domAttributesList){
		// create the storage object
		var attributes = {};
		
		// search for attributes
		for (var i = 0; i < domAttributesList.length; i++) {
			// get the attribute
			var attributeNode = domAttributesList[i];
			
			// set the data
			attributes[attributeNode.name] = attributeNode.value;
		}
		
		return attributes;
	}
};

/**
 * Exceptions namespace
 * @namespace syslib.exceptions
 */
syslib.exceptions = {};

/**
 * Basic syslib exception class
 * @class syslib.ui.exceptions.Exception
 */
syslib.exceptions.Exception = __class();
syslib.exceptions.Exception.prototype = {
	__className: "syslib.exception.Exception",
	message: null,
	
	__construct: function(message){
		this.__className = "syslib.exception.Exception";
		this.message = message;
	}
};

/**
 * Used when a file was not been loaded yet
 * @class syslib.exceptions.FileNotLoadedException
 */
syslib.exceptions.FileNotLoadedException = __class();
syslib.exceptions.FileNotLoadedException.prototype = {
	__className: "syslib.exception.FileNotLoadedException",
	message: null,
	file: null,
	
	__construct: function(file){
		this.__className = "syslib.exception.FileNotLoadedException";
		this.file = file;
		this.message = "The file " + file + " was not been loaded yet";
	}
};

/**
 * Used when a file was not been found
 * @class syslib.exceptions.FileNotFoundException
 */
syslib.exceptions.FileNotFoundException = __class();
syslib.exceptions.FileNotFoundException.prototype = {
	__className: "syslib.exception.FileNotFoundException",
	message: null,
	file: null,
	
	__construct: function(file){
		this.__className = "syslib.exception.FileNotFoundException";
		this.file = file;
		this.message = "The file " + file + " was not been found";
	}
};

/**
 * The tag library class, which is responsable for handle parse requests and forward it to a parser
 * @namespace syslib.taglib
 * @author Gabriel Ricci
 * @static
 */
syslib.taglib = {
	MAX_LOAD_TRIES: 25, // in milliseconds, MAX_LOAD_TRIES * 1000
	MAX_ERRORS: 25,
	
	TYPE_BASIC: "BASIC_TAG",
	TYPE_VISUAL: "VISUAL_TAG",
	
	tags: {},
	
	__onParseBodyListeners: [],
	
	registerTag: function(tag, options){
		// format the options
		options = syslib.object.extend({
			innerContent: true
		}, options);
		
		// create the specification
		if (__valid(options.namespaceName) && __valid(options.parser) && typeof tag == 'string') {
			var spec = {
				tagName: tag,
				namespaceName: options.namespaceName,
				parser: options.parser
			};
			
			// register
			this.tags[tag] = spec;
			
			// delete unused variables
			spec = null;
		} else {
			syslib.messages.error('syslib.taglib.registerTag(): Invalid specification for tag ' + tag);
		}
	},
	
	isRegistered: function(tag){
		return __valid(this.tags[tag]);
	},
	
	parseAndAppend: function(text, container){
		// log
		syslib.messages.info("syslib.taglib.parseAndAppend(): Starting parser...");
		
		// create the parser
		var parser = new syslib.taglib.parser2(text, __id(container), syslib.taglib.parser2.INSERT_MODE_INSIDE, {
			onComplete: function(){
				syslib.messages.info("syslib.taglib.parseAndAppend(): Parser completed !");
			}
		});
		
		// delete the parser
		parser = null;
	},
	
	parseBody: function(){
		// set the body parsers
		this.bodyParsers = {};
		
		// get the script elements
		var scriptElements = document.body.getElementsByTagName("script");
		
		// search the scripts
		for (var i = 0; i < scriptElements.length; i++) {
			// get the script
			var script = scriptElements[i];
			var type = script.getAttribute("type");
			
			// check if the script is a syslib code
			if (__valid(type) && type.toLowerCase() == "application/syslib+xml") {
				// log
				syslib.messages.info("syslib.taglib.parseBody(): Starting parser...");
				
				// create the 
				var parser = new syslib.taglib.parser2(script.innerHTML, script.parentNode, {
					onComplete: function(){
						// call the events
						this.__callEvents();
					}
.applyTo(this)
				});
				
				// delete the parser
				parser = null;
			}
		}
	},
	
	onParseBody: function(callback){
		this.__onParseBodyListeners.push(callback);
	},
	
	__callEvents: function(){
		// call the event handlers
		for (var i = 0; i < this.__onParseBodyListeners.length; i++) {
			// get the handler
			var handler = this.__onParseBodyListeners[i];
			
			// check the type
			if (__valid(handler) && typeof handler == "function") {
				// call
				handler();
			}
		}
	}
};

/** 
 * The new tag library parser
 * @class syslib.taglib.parser2
 * @author Gabriel Ricci
 * @since 0.5.3
 */
syslib.taglib.parser2 = __class();
syslib.taglib.parser2.prototype = {
	root: null,
	container: null,
	insertBeforeOf: null,
	loadAttempts: null,
	errors: 0,
	conversors: null,
	onComplete: null,
	
	__CONVERSION_TABLE: {
		"&nbsp;": " ",
		"&": "&#38;"
	},
	
	__construct: function(content, container, options){
		this.loadAttempts = {};
		this.errors = 0;
		
		// create the root container
		var root = syslib.xml.createFromText("<root>" + syslib.string.encode(content, this.__CONVERSION_TABLE) + "</root>");
		
		// check the root
		if (!root) {
			syslib.messages.error("syslib.taglib.parser2(): Could not parse this block because the XML is invalid or not well-formed!");
			return false;
		}
		
		// set the container
		if (!__valid(container)) {
			return false;
		}
		this.container = container;
		
		// set the onComplete function, if it's available
		if (__valid(options) && __valid(options.onComplete) && typeof options.onComplete == "function") {
			this.onComplete = options.onComplete;
		}
		
		// set the root
		this.root = root;
		
		// parse the tags
		this.parseTree();
	},
	
	parseTree: function(){
		// get the root element
		var root = this.root.childNodes[0];
		
		// search the nodes
		while (root.childNodes.length > 0) {
			// erase the conversors list
			this.conversors = [];
			
			// get the current node
			var node = root.childNodes[0];
			
			try {
				// parse the tag
				this.parseXMLTree(node, this.container);
				
				// erase the conversors list
				this.conversors = [];
				
				// delete this node
				root.removeChild(node);
			} catch (e) {
				if (e instanceof syslib.exceptions.FileNotFoundException) {
					// log the error message
					syslib.messages.error("syslib.taglib.parser2.parseTree(): Some required files have not been found, this parser can't continue!");
					return false;
				} else {
					// increase the error count
					this.errors++;
					
					// check if the number of errors reached the MAX_ERRORS limit
					if (this.errors >= syslib.taglib.MAX_ERRORS) {
						return false;
					}
					
					// check if the element can be removed
					if (__valid(root) && __valid(node)) {
						// delete this node
						root.removeChild(node);
					}
					
					// log the error messagex
					syslib.messages.error("syslib.taglib.parser2.parseTree(): Fatal error: " + e.message + " - Please report this error in http://syslibjs.googlecode.com/");
				}
			}
		}
		
		// check if there's an onComplete function
		if (__valid(this.onComplete) && typeof this.onComplete == "function") {
			this.onComplete();
		}
	},
	
	parseXMLTree: function(xmlNode, container){
		// check if the node is an element
		if (xmlNode.nodeType == 3) {
			if (syslib.util.isIE()) {
				// on ie, appendChild throws an exception, so we get the nodeValue
				container.innerHTML = container.innerHTML + xmlNode.nodeValue;
			} else {
				// append to the html and return
				container.appendChild(xmlNode.cloneNode(true));
			}
			
			// retorna
			return true;
		}
		
		// check the node and the tag name
		if (!__valid(xmlNode) || !__valid(xmlNode.tagName)) {
			return false;
		}
		
		// get the tag name
		tagName = xmlNode.tagName.toLowerCase();
		
		// parse
		if (this.isCustomTag(tagName)) {
			// non-standard tag, try to convert it
			this.parseCustomTag(xmlNode, tagName, container);
		} else {
			// standard tag, create it
			this.parseHTMLTag(xmlNode, container);
		}
	},
	
	parseChildren: function(node, container){
		// search for child nodes
		if (node.hasChildNodes) {
			// get the child data
			var childNodes = node.childNodes;
			var childLength = childNodes.length;
			
			// search the data
			for (var i = 0; i < childLength; i++) {
				// get the children
				var child = childNodes[i];
				
				// parse
				this.parseXMLTree(child, container);
			}
		}
	},
	
	parseHTMLTag: function(xmlNode, container){
		// convert the xml tag to an html tag
		var createdElement = syslib.xml.convertXmlToHTML(xmlNode);
		
		// IEFIX: On Internet Explorer, if a table is dinamically created, it must have a tBody inside it, 
		// IEFIX: so we create a tbody, if the table doesn't have one
		if (tagName.toLowerCase() == "tr" && container.tagName.toLowerCase() == "table") {
			// check if the table have a tbody
			if (container.tBodies.length === 0) {
				// no tbody in the table, create a new tbody and set as the container
				container.appendChild(document.createElement("tbody"));
				container = container.tBodies[0];
			} else {
				// table have a tbody, set as the container
				container = container.tBodies[0];
			}
		}
		
		// append to the html tree
		container.appendChild(createdElement);
		
		// parse the children
		this.parseChildren(xmlNode, createdElement);
		
		// return the created element
		return createdElement;
	},
	
	parseCustomTag: function(myNode, tagName, container, removeNode){
		// get the tag specification
		var tagSpecification = syslib.taglib.tags[tagName];
		var loadAttempts = this.loadAttempts[tagName];
		
		// create the parser
		var conversorObject = syslib.object.findFromName(tagSpecification.parser);
		
		// check if the parser is valid
		if (!__valid(conversorObject)) {
			//  check if the max number of errors was reached
			if (__valid(loadAttempts) && loadAttempts >= syslib.taglib.MAX_LOAD_TRIES) {
				// show the error
				syslib.messages.error("syslib.taglib.parser2.convertCustomTag(): The tag " + tagName + " has reached the maximum number of load attempts!");
				
				// throw the exception
				throw new syslib.exceptions.FileNotFoundException("[tag " + tagName + " classfiles]");
			} else if (__valid(loadAttempts)) {
				// increase the number of load attempts
				this.loadAttempts[tagName]++;
			} else {
				// load process not started, load the class files
				syslib.io.importClass(tagSpecification.namespaceName);
				
				// set the number of load attempts
				this.loadAttempts[tagName] = 0;
			}
			
			// schedule another parse
			setTimeout(function(){
				this.parseCustomTag(myNode, tagName, container, removeNode);
			}
.applyTo(this), 1000);
			
			// return
			return false;
		}
		
		// create the conversor
		var conversor = new conversorObject();
		
		// get the tag attributes
		var attributes = syslib.xml.convertAttributesToObject(myNode.attributes);
		
		// convert
		var component = this.executeConversor(conversor, tagName, attributes, container);
		
		// parse the children
		this.parseChildren(myNode, component);
		
		// return
		return component;
	},
	
	executeConversor: function(conversor, tagName, attributes, container){
		// update the required definitions
		conversor.__tagName = tagName;
		conversor.__attributes = attributes;
		conversor.__container = container;
		
		// convert
		conversor.execute();
		
		// store this conversor
		this.conversors.push(conversor);
		
		// return
		return conversor.getComponent();
	},
	
	isCustomTag: function(tagName){
		// check the integrity
		if (!__valid(tagName)) {
			return false;
		}
		
		// get the tags
		tags = syslib.taglib.tags;
		
		// search the custom tags
		for (var tag in tags) {
			if (tagName.toLowerCase() == tag.toLowerCase()) {
				return true;
			}
		}
		
		// no custom tags found, return false
		return false;
	}
};


/**
 * The general message class for debugging
 * @class syslib.message
 */
syslib.message = __class();
syslib.message.prototype = {
	message: null,
	tag: null,
	color: null,
	createDate: null,
	
	/**
	 * @constructor
	 * @param {String} message
	 * @param {String} tag
	 */
	__construct: function(message, tag){
		this.message = message;
		this.tag = tag;
		this.color = this.getColorForTag(tag);
		this.createDate = syslib.date.make("h:i:s");
	},
	
	getColorForTag: function(tag){
		if (tag === 'error') {
			return 'red';
		} else if (tag === 'warning') {
			return 'yellow';
		} else if (tag === 'info') {
			return 'green';
		} else {
			return 'white';
		}
	}
};

/**
 * The static messages class that control all messages
 * @namespace syslib.messages
 * @author Gabriel Ricci
 * @static
 */
syslib.messages = {
	entries: [],
	
	add: function(message, tag){
		if (!syslib.debug) {
			return false;
		}
		var entry = new syslib.message(message, tag || "generic-message");
		this.entries.push(entry);
		if (syslib.console.element !== null) {
			syslib.console.updateEntries();
		}
	},
	
	clear: function(){
		this.entries = [];
		if (syslib.console.element !== null) {
			syslib.console.updateEntries();
		}
	},
	
	error: function(message){
		this.add(message, 'error');
	},
	
	warning: function(message){
		this.add(message, 'warning');
	},
	
	info: function(message){
		this.add(message, 'info');
	},
	
	getEntries: function(){
		return syslib.array.clone(this.entries);
	}
};

/**
 * The console class
 * @namespace syslib.console
 * @author Gabriel Ricci
 * @static
 */
syslib.console = {
	id: 'syslib_logger',
	console: null,
	entries: null,
	command: null,
	opener: null,
	
	bottomPos: 0,
	leftPos: 0,
	
	positionTimer: null,
	
	createConsole: function(){
		try {
			syslib.loadStyleForComponent('console');
			
			objson = ["div", {
				'class': 'console-main',
				'id': this.id,
				'innerName': 'main'
			}, ["form", {
				"name": 'console_form',
				"id": "console_form"
			}, ["table", {
				"width": "100%",
				"border": "0",
				"cellpadding": "0",
				"cellspacing": "0",
				"class": "console-top"
			}, ["tbody", ["tr", ["td", {
				"width": "40%",
				"id": "console_title"
			}, "SyslibJS " + syslib.version + " console"], ["td", {
				"align": "right",
				"width": "60%",
				"id": "console_buttons"
			}, ["input", {
				"type": "text",
				"id": "console_command",
				"size": "60",
				"class": "console-command"
			}], "&nbsp", ["input", {
				"type": "submit",
				"id": "console_run",
				"value": "Run",
				"class": "console-button",
				"onclick": "syslib.console.runCommand(); return false;"
			}], "&nbsp", ["input", {
				"type": "button",
				"id": "console_close",
				"value": "Close",
				"class": "console-button",
				"onclick": "syslib.console.close()"
			}]]]]]], ["div", {
				"innerName": "entries",
				"class": "console-entries"
			}]];
			
			openerjson = ["div", {
				"class": 'console-open',
				'id': 'console-opened',
				'align': 'center'
			}, ["a", {
				"href": "javascript:void(0);",
				"innerName": 'opener'
			}, "Toggle console"]];
			
			this.console = syslib.element.createFromJSON(false, objson);
			this.opener = syslib.element.createFromJSON(false, openerjson);
			
			document.body.appendChild(this.console.element);
			document.body.appendChild(this.opener.element);
			
			this.entries = this.console.references.entries;
			this.command = __id('console_command');
			
			syslib.event.listen('click', this.opener.references.opener, function(){
				syslib.console.toggle();
			});
			syslib.event.listen('click', __id('console_close'), function(){
				syslib.console.close();
			});
			syslib.event.listen('submit', __id('console_form'), function(evt){
				syslib.console.runCommand();
				syslib.event.stopPropagation(evt);
			});
			
			this.close();
		} catch (e) {
			alert("ERROR: Could not start the console system: " + e.message);
		}
	},
	
	runCommand: function(){
		var command = this.command.value;
		try {
			if (command === 'clear') {
				syslib.messages.clear();
			} else if (command === 'help') {
				var help = 'The commands are: <br /><br />  - clear: clear the console<br />  - help: show this message<br />  - close: close the console';
				syslib.messages.add(help, 'help');
			} else if (command === 'close') {
				syslib.console.close();
			} else {
				eval(command);
			}
		} catch (e) {
			syslib.messages.error("System could not execute the command [" + command + "] - reason: " + e.message);
			this.command.value = '';
			return false;
		}
		syslib.messages.info("Command [" + command + "] executed with success!");
		this.command.value = '';
		return true;
	},
	
	setPosition: function(){
		try {
			if (!syslib.util.isIE()) {
				this.console.element.style.position = "fixed";
				this.console.element.style.left = "0";
				this.console.element.style.bottom = "0";
			} else {
				var pageSize = document.documentElement.offsetHeight;
				var scrlSize = document.body.scrollTop;
				var topPosit = ((pageSize - 240) + scrlSize) + "px";
				
				this.console.element.style.left = '0';
				this.console.element.style.top = topPosit;
			}
		} catch (e) {
			syslib.messages.error("Could not set the position of the console, the reason is: " + e.message);
		}
	},
	
	updateEntries: function(){
		if (!__valid(this.entries)) {
			return false;
		}
		try {
			syslib.element.update(this.entries, '');
			var entries = syslib.messages.getEntries();
			entries.reverse();
			for (var i = 0; i < entries.length; i++) {
				var obj = entries[i];
				var color = obj.color;
				var content = document.createElement('font');
				content.color = color;
				content.innerHTML = "" + obj.createDate + " [ " + obj.tag + " ] - " + obj.message;
				content.innerHTML += "<br /><br />";
				this.entries.appendChild(content);
			}
		} catch (e) {
			alert("ERROR: Could not update the console system, see the error: " + e.message);
		}
	},
	
	close: function(){
		if (!syslib.util.valid(this.console)) {
			this.createConsole();
		}
		clearInterval(this.positionTimer);
		syslib.element.hide(this.console.element);
	},
	
	open: function(){
		if (!syslib.util.valid(this.console)) {
			this.createConsole();
		}
		this.setPosition();
		this.updateEntries();
		syslib.element.show(this.console.element);
		this.positionTimer = setInterval(syslib.console.setPosition.applyTo(this), 200);
	},
	
	toggle: function(){
		if (!syslib.util.valid(this.console)) {
			this.createConsole();
		}
		if (syslib.element.isVisible(this.console.element)) {
			this.close();
		} else {
			this.open();
		}
	}
};

/**
 * The profiling class
 * @namespace syslib.profiling
 * @author Gabriel Ricci
 * @static
 */
syslib.profiling = {
	storage: {},
	
	runFunction: function(funct, identification, timePart){
		if ("hisu".indexOf(timePart) == -1) {
			return false;
		}
		if (!__valid(identification) || identification === "") {
			return false;
		}
		
		if (typeof funct == "function") {
			if (syslib.debug === true) {
				var start = syslib.date.make(timePart);
				funct();
				var totaltime = syslib.date.make(timePart) - start;
				syslib.messages.info("PROFILING :: " + identification + " :: Code executed in " + totaltime + " " + timePart);
			} else {
				funct();
			}
		} else {
			return false;
		}
	},
	
	start: function(identification, tPart){
		if ("hisu".indexOf(tPart) == -1) {
			return false;
		}
		if (!__valid(identification) || identification === "") {
			return false;
		}
		if (!syslib.debug) {
			return false;
		}
		
		this.storage[identification] = {
			timePart: tPart,
			start: syslib.date.make(tPart),
			end: false,
			totaltime: false
		};
	},
	
	end: function(identification){
		if (!__valid(identification) || identification === "") {
			return false;
		}
		if (!__valid(this.storage[identification])) {
			return false;
		}
		if (!syslib.debug) {
			return false;
		}
		
		var entry = this.storage[identification];
		
		if (__valid(entry.end) || __valid(entry.totaltime)) {
			return false;
		}
		
		entry.end = syslib.date.make(entry.timePart);
		entry.totaltime = entry.end - entry.start;
		
		syslib.messages.info("PROFILING :: " + identification + " :: Code executed in " + entry.totaltime + " " + entry.timePart);
	}
};

/**
 * The browser history and controls (back, forward, reload and bookmarks) class
 * @namespace syslib.history
 * @author Gabriel Ricci
 * @static
 */
syslib.history = {
	currentHash: "",
	working: false,
	interval: false,
	
	init: function(){
		// create the controller iframe
		var ctliframe = document.createElement("iframe");
		
		// set the properties
		ctliframe.id = 'syslib-history';
		ctliframe.style.display = 'none';
		
		// append to the body
		document.body.appendChild(ctliframe);
		
		// create an interval for checking the history
		this.interval = setInterval(function(){
			syslib.history.checkPage()
		}, 100);
	},
	addEntry: function(container, page){
		this.working = true;
		
		var hash = this.createHash(container, page);
		var path = syslib.path + "controls.html?hash=" + hash;
		var ctliframe = __id('syslib-history');
		
		if (!__valid(ctliframe)) {
			clearInterval(this.interval);
			this.init();
		}
		
		if (syslib.util.isIE()) {
			ctliframe.src = path;
		}
		
		location.hash = hash;
		this.currentHash = "#" + hash;
		this.working = false;
	},
	
	createHash: function(container, page){
		var hash = '';
		if (typeof container == 'string') {
			hash = encodeURIComponent(container + "||" + page);
		} else {
			hash = encodeURIComponent(container.id + "||" + page);
		}
		
		return hash;
	},
	
	checkPage: function(){
		if (this.working) {
			return true;
		}
		
		var pageHash = '';
		if (syslib.util.isIE()) {
			pageHash = decodeURIComponent(location.hash);
		} else {
			pageHash = location.hash;
		}
		
		var currHash = decodeURIComponent(this.currentHash);
		if (currHash == pageHash || this.working === true) {
			return true;
		} else {
			this.currentHash = encodeURIComponent(pageHash);
			this.load(pageHash);
		}
	},
	
	load: function(hash){
		var currHash = decodeURIComponent(hash);
		var spec = currHash.split("||");
		var container = spec[0];
		var page = spec[1];
		container = container.substr(1, container.length);
		
		if (!__id(container)) {
			return false;
		}
		
		new syslib.ajax.request(page, {
			destiny: container,
			store: false
		});
	},
	
	reload: function(){
		this.load(this.currentHash);
	}
};

/**
 * The date namespace
 * @namespace syslib.date
 * @author Gabriel Ricci
 * @static
 */
syslib.date = {
	weekStartDay: 0,
	
	make: function(format, currentTime){
		var now = (typeof currentTime === 'object' && __valid(currentTime)) ? currentTime : new Date();
		var formatted = format;
		
		var hour = syslib.string.pad(now.getHours().toString(), 2, "0");
		var minutes = syslib.string.pad(now.getMinutes().toString(), 2, "0");
		var seconds = syslib.string.pad(now.getSeconds().toString(), 2, "0");
		var millis = now.getTime().toString();
		
		var day = syslib.string.pad(now.getDate().toString(), 2, "0");
		var month = syslib.string.pad((now.getMonth() + 1).toString(), 2, "0");
		var fullMonth = this.getMonthName(now.getMonth() + 1);
		var fullYear = now.getFullYear();
		var year = now.getYear();
		var week = now.getWeekOfYear();
		var weekday = now.getDay();
		
		formatted = formatted.replace(/[h]/, hour);
		formatted = formatted.replace(/[i]/, minutes);
		formatted = formatted.replace(/s/, seconds);
		formatted = formatted.replace(/u/, millis);
		
		formatted = formatted.replace(/d/, day);
		formatted = formatted.replace(/w/, weekday);
		formatted = formatted.replace(/m/, month);
		formatted = formatted.replace(/M/, fullMonth);
		formatted = formatted.replace(/[Yy]/, fullYear);
		formatted = formatted.replace(/[W]/, week);
		formatted = formatted.replace(/[w]/, weekday);
		
		return formatted;
	},
	
	getWeekOfYear: function(day){
		// create the first day of year date
		var firstDayOfYear = new Date(day.getFullYear(), 0, 1);
		
		// calculates the difference (in days) to the start of the year
		var daysDiff = ((day - firstDayOfYear) / 86400000) + 1;
		
		// get the week number calculing the first week of the year as the week that containts the first day of the year
		var week = Math.ceil((daysDiff + firstDayOfYear.getDay()) / 7);
		
		// return the week number calculing the first week of the year as the week that have the first [weekStartDay] of the year
		if (firstDayOfYear.getDay() != syslib.date.weekStartDay) {
			if (week == 1) {
				// clone the object
				var workDay = new Date();
				workDay.setTime(day.getTime());
				
				// reduces one day on the date
				workDay.setDate(workDay.getDate() - 1);
				
				// call this same function
				return syslib.date.getWeekOfYear(workDay);
			} else {
				return week - 1;
			}
		} else {
			return week;
		}
	},
	
	getLocaleDate: function(){
		dateObj = new Date();
		return dateObj.toLocaleDateString();
	},
	
	getMonthName: function(month){
		// create the names
		var months = ["Janeiro", "Fevereiro", "Mar�o", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"];
		
		// get the name of the month and return
		return months[month - 1];
	},
	
	validate: function(theDate){
		var reDate = /^((0[1-9]|[12]\d)\/(0[1-9]|1[0-2])|30\/(0[13-9]|1[0-2])|31\/(0[13578]|1[02]))\/\d{4}$/;
		if (!reDate.test(theDate)) {
			return false;
		} else {
			return true;
		}
	},
	
	__prototype: {
		getWeekOfYear: function(){
			return syslib.date.getWeekOfYear(this);
		}
	}
};

/**
 * Aliases and extensions for date class
 */
__addMethods(Date.prototype, syslib.date.__prototype);
__addMethods(Date, syslib.date);


/**
 * The class that controls the ajax requests
 * @namespace syslib.ajax
 * @author Gabriel Ricci
 * @static
 */
syslib.ajax = {
	createRequestObject: function(){
		var request = false;
		if (window.XMLHttpRequest) {
			request = new XMLHttpRequest();
		} else if (window.ActiveXObject) {
			try {
				request = new ActiveXObject("Msxml2.XMLHTTP");
			} catch (e) {
				try {
					request = new ActiveXObject("Microsoft.XMLHTTP");
				} catch (ex) {
					syslib.messages.error("Your browser doesn't support XMLHTTP [AJAX] Requests!");
					request = false;
				}
			}
		}
		
		// retorna
		return request;
		
	},
	
	getDefaultOptions: function(){
		var options = {
			destiny: false,
			clearDestiny: true,
			method: 'POST',
			charset: "UTF-8",
			contentType: 'application/x-www-form-urlencoded',
			parameters: '',
			asynchronous: true,
			form: false,
			store: true,
			evalTags: true,
			evalScripts: true,
			evalStyles: true,
			callHandlers: true,
			autoSend: true
		};
		
		return options;
	},
	
	getDefaultRequestHeaders: function(){
		var headers = {
			'X-Requested-With': 'XMLHttpRequest',
			'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
		};
	},
	
	evalStyles: function(text){
		firstPos = text.indexOf("<style");
		while (firstPos != -1) {
			endFirstPos = text.indexOf(">", firstPos + 1);
			endPos = text.indexOf("</style>", endFirstPos + 1);
			elText = text.substring((endFirstPos + 1), endPos);
			
			elemento = document.createElement("style");
			elemento.text = elText;
			
			document.body.appendChild(elemento);
			
			firstPos = text.indexOf("<style", endPos + 1);
		}
	},
	
	evalScripts: function(text){
		// create the regex
		var regex = /<script[^>]*>([\u0001-\uFFFF]*?)<\/script>/;
		
		// execute
		var matches = text.match(regex);
		
		// validate the result
		if (!syslib.util.valid(matches)) {
			return true;
		}
		
		// get the length
		var length = matches.length;
		
		// search the matches
		for (var i = 0; i < length; i++) {
			var scriptFragment = matches[i];
			
			// test the fragment
			if (!regex.test(scriptFragment)) {
				try {
					// execute
					eval(scriptFragment);
				} catch (e) {
					syslib.messages.error("Javascript error on request response: " + e.message);
				}
			}
		}
	}
};

/**
 * The ajax request class
 * @class syslib.ajax.request
 * @author Gabriel Ricci
 */
syslib.ajax.request = __class();
syslib.ajax.request.prototype = {
	url: null,
	options: null,
	headers: null,
	request: null,
	
	__construct: function(url, options, headers){
		// format the options and the headers
		if (!syslib.util.valid(options)) {
			options = {};
		}
		if (!syslib.util.valid(headers)) {
			headers = {};
		}
		
		// prepare the basic variables
		this.url = url;
		this.request = syslib.ajax.createRequestObject();
		this.headers = syslib.object.extend(syslib.ajax.getDefaultRequestHeaders(), headers);
		this.options = syslib.object.extend(syslib.ajax.getDefaultOptions(), options);
		
		// call the handlers
		if (this.options.callHandlers) {
			syslib.ajax.handlers.__onCreate(this.request, this.options);
		}
		
		// prepare the parameters
		this.prepareParameters();
		
		if (this.options.autoSend === true) {
			this.prepareAndSend();
		}
		
		return this;
	},
	
	prepareParameters: function(){
		// serialize the parameters, if needed
		if (typeof this.options.parameters === 'object') {
			this.options.parameters = syslib.object.serialize(this.options.parameters);
		}
		
		// append the parameters in the url
		if (__valid(this.options.parameters) && this.options.parameters != '') {
			if (this.url.indexOf("?") !== -1) {
				this.url += "&" + this.options.parameters;
			} else {
				this.url += "?" + this.options.parameters;
			}
			
			// set the full parameters
			this.parameters = this.url.split("?")[1];
		}
		
		// set the form data into the parameters
		if (syslib.util.valid(this.options.form) && typeof this.options.form === 'object') {
			this.options.parameters += "&" + syslib.form.serialize(this.options.form);
			this.options.store = false;
		}
	},
	
	prepareAndSend: function(){
		if (this.options.method.toLowerCase() == 'post') {
			this.headers["Content-type"] = this.options.contentType + (this.options.encoding ? '; charset=' + this.options.encoding : '');
		}
		
		this.request.open(this.options.method, this.url, this.options.asynchronous);
		
		this.request.onreadystatechange = syslib.functions.applyTo(function(){
			this.readyStateChanged();
		}, this);
		
		for (var header in this.headers) {
			try {
				this.request.setRequestHeader(header, this.headers[header]);
			} catch (e) {
				syslib.messages.error("syslib.ajax.request.prepareAndSend(): Error setting the request header [" + header + "=" + this.headers[header] + "]: " + e.message);
			}
		}
		
		this.request.send(this.options.parameters);
	},
	
	readyStateChanged: function(){
		if (this.request.readyState === 4) {
			syslib.ajax.handlers.__onComplete(this.request, this.options);
			if (this.request.status === 200) {
				this.onSuccess();
				if (typeof this.options.onSuccess === 'function') {
					this.options.onSuccess(this.request, this.options);
				}
			} else {
				this.onError();
				if (typeof this.options.onError === 'function') {
					this.options.onError(this.request.status, this.request, this.options);
				}
			}
		}
	},
	
	onSuccess: function(){
		if (syslib.util.valid(this.options.destiny)) {
			var destiny = __id(this.options.destiny);
			if (this.options.clearDestiny) {
				syslib.element.update(destiny, '');
			}
			if (this.options.evalTags) {
				var domTree = syslib.taglib.parseAndAppend(this.request.responseText, destiny);
			} else {
				destiny.innerHTML += this.request.responseText;
			}
			
			if (this.options.store === true) {
				syslib.history.addEntry(destiny.id, this.url);
			}
		}
		if (this.options.evalStyles) {
			syslib.ajax.evalStyles(this.request.responseText);
		}
		if (this.options.evalScripts) {
			syslib.ajax.evalScripts(this.request.responseText);
		}
	},
	
	onError: function(){
		syslib.messages.error("Could not complete the request, the server returned the error code " + this.request.status);
	}
};

/**
 * The ajax request event handlers
 * @namespace syslib.ajax.handlers
 */
syslib.ajax.handlers = {
	__onCreate: function(){
	},
	__onComplete: function(){
	},
	
	/**
	 * Set the default handler when the event LOADING has been triggered
	 * @param {Function} handler The handler
	 */
	onLoading: function(handler){
		if (typeof handler == 'function') {
			syslib.ajax.handlers.__onCreate = handler;
		} else {
			syslib.messages.error("syslib.ajax.handlers.onLoading(): Invalid loading handler: Undefined, null or not a function!");
		}
	},
	
	/**
	 * Set the default handler when the event COMPLETE has been triggered
	 * @param {Function} handler The handler
	 */
	onComplete: function(handler){
		if (typeof handler == 'function') {
			syslib.ajax.handlers.__onComplete = handler;
		} else {
			syslib.messages.error("syslib.ajax.handlers.onComplete(): Invalid loading handler: Undefined, null or not a function!");
		}
	}
};

/**
 * The older ajax requests class (replaced by syslib.ajax)
 * @namespace syslib.request
 * @author Gabriel Ricci
 * @deprecated
 */
syslib.request = {
	get: function(requestFile, container, options, getParameters){
		options = (typeof options == 'object') ? options : {};
		
		options.destiny = (!syslib.util.valid(container)) ? false : container;
		requestFile = (syslib.util.valid(getParameters)) ? requestFile + "?" + getParameters : requestFile;
		
		var request = new syslib.ajax.request(requestFile, options);
	},
	
	openPage: function(page, args){
		if (args === undefined || args === "undefined") {
			window.open(page, 'newPage');
		} else {
			window.open(page, 'newPage', args);
		}
	},
	
	setLoadingHandler: syslib.ajax.handlers.onLoading,
	setResponseHandler: syslib.ajax.handlers.onComplete
};

/**
 * The input/output class
 * @namespace syslib.io
 * @author Gabriel Ricci
 * @static
 */
syslib.io = {
	// states
	LOADING: 0,
	LOADED: 1,
	ERROR: 2,
	
	// set the timeout
	TIMEOUT: 13,
	
	scripts: {},
	styles: {},
	
	checkScript: function(filename, attempt){
		if (this.scripts[filename] != this.LOADED) {
			if (attempt >= this.TIMEOUT) {
				this.scripts[filename] = this.ERROR;
			} else {
				setTimeout(function(){
					this.checkScript(filename, attempt++);
				}, 1000);
			}
		}
	},
	
	importClass: function(className, options){
		// format the options
		options = syslib.object.extend({
			"className": className
		}, options);
		
		// format the path
		var path = syslib.srcPath +
		syslib.string.replace(".", "/", syslib.string.replace("syslib.", "", className)) +
		".js";
		
		// import
		var filename = this.importScript(path, options);
		
		// return
		return filename;
	},
	
	importScript: function(filename, options){
		// format the options
		options = syslib.object.extend({
			onComplete: function(){
				return;
			}
		}, options);
		
		// check if the script if already loaded
		var scripts = this.scripts;
		for (var script in scripts) {
			if (script == filename) {
				if (scripts[filename].state == this.LOADED) {
					if (__valid(options.onComplete) && typeof options.onComplete == 'function') {
						syslib.messages.info('syslib.io.importScript(): script ' + filename + ' is already loaded, calling onComplete() !');
						options.onComplete(filename);
					} else {
						syslib.messages.info('syslib.io.importScript(): script ' + filename + ' is already loaded!');
					}
				}
				return;
			}
		}
		
		// store
		syslib.io.scripts[filename] = {
			state: this.LOADING,
			onComplete: options.onComplete,
			filename: filename
		};
		
		// declare the needed variables
		var filenameAc = null;
		
		// anti-cache
		if (filename.indexOf("?") != -1) {
			filenameAc = filename + "&ac=" + Math.floor(Math.random() * 1111);
		} else {
			filenameAc = filename + "?ac=" + Math.floor(Math.random() * 1111);
		}
		
		// log
		syslib.messages.info('syslib.io.importScript(): Trying to load script ' + filenameAc + " !");
		
		// create the loaded
		var script = document.createElement("script");
		script.setAttribute("src", filenameAc);
		document.getElementsByTagName('head')[0].appendChild(script);
		
		// event listeners
		script.onreadystatechange = function(){
			if (this.readyState == "loaded") {
				var file = this.getAttribute("src");
				syslib.io.scripts[filename].state = syslib.io.LOADED;
				syslib.io.scripts[filename].onComplete(filename);
			}
		};
		script.onload = function(){
			var file = this.getAttribute("src");
			syslib.io.scripts[filename].state = syslib.io.LOADED;
			syslib.io.scripts[filename].onComplete(filename);
		};
		
		return filename;
	},
	
	importStyle: function(filename){
		// CHECK
		var styles = this.styles;
		for (var style in styles) {
			if (style == filename) {
				return;
			}
		}
		
		// IMPORT
		var style = document.createElement("link");
		style.rel = 'stylesheet';
		style.type = 'text/css';
		style.href = filename;
		document.getElementsByTagName('head')[0].appendChild(style);
		
		// EVENTS
		styles[filename] = this.LOADED;
	}
};
